/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package vmcs.controller;

import java.awt.Frame;

import java.util.HashMap;
import java.util.Map;
import vmcs.boundary.CustomerPanelNew;
import vmcs.boundary.CustomerPanelNew.CompType;
import vmcs.boundary.SimulatorControlPanel;
import vmcs.controller.statePattern.TransactionController;
import vmcs.entity.CashStoreItem;
import vmcs.entity.Coin;
import vmcs.entity.StoreItem;
import vmcs.observer.StoreItemChangeManager;
import vmcs.observer.StoreItemChangeManagerRegistry;
import vmcs.observer.StoreItemObserver;
import vmcs.utility.AccessManager;

/**
 *
 * @author eileen
 */
public class CustomerController implements StoreItemObserver {

    private SimulationController simulatorCtrl;
    private MaintenanceController maintenanceCtrl;
    private StoreController storeCtrl;
    private CustomerPanelNew customerPanel;
    private MainController mCtrl;
    private Map<StoreItem, Integer> itemEventMap = new HashMap< StoreItem, Integer>();

    public CustomerController(MainController mctrl, MaintenanceController mtnCtrl) {
        mCtrl = mctrl;
        maintenanceCtrl = mtnCtrl;
        TransactionController.instance().setCustomerController(this);
        
        // get change manager for drink store item
        StoreItemChangeManager drinkMgr = StoreItemChangeManagerRegistry.getManager(StoreItemChangeManagerRegistry.StoreItemType.Drink);
        // register itself for updates
        drinkMgr.register(this, StoreItemChangeManager.EVENT_QUANTITYDRINKCHANGE);
        drinkMgr.register(this, StoreItemChangeManager.EVENT_DRINKVALUECHANGE);
        StoreItemChangeManager cointMgr = StoreItemChangeManagerRegistry.getManager(StoreItemChangeManagerRegistry.StoreItemType.Cash);
        cointMgr.register(this, StoreItemChangeManager.EVENT_QUANTITYCOINCHANGE);
        // OBSERVER IMPL END
    }

    public void setStoreCtrl(StoreController storeCtrl) {
        this.storeCtrl = storeCtrl;
    }

    public StoreController getStoreCtrl() {
        return storeCtrl;
    }

    public SimulationController getSimulatorCtrl() {
        return simulatorCtrl;
    }

    public void setSimulatorCtrl(SimulationController simulatorCtrl) {
        this.simulatorCtrl = simulatorCtrl;
    }

    public MaintenanceController getMaintenanceCtrl() {
        return maintenanceCtrl;
    }

    public void setMaintenanceCtrl(MaintenanceController maintenanceCtrl) {
        this.maintenanceCtrl = maintenanceCtrl;
    }

    public AccessManager getAccessManager() {
        return maintenanceCtrl.getAccessManager();
    }

    public void onInsertCoinEvent(final CashStoreItem item, final String coinsLabel, final int coinIdx) {
        double weight = 999.99;
        Coin coin;
        if (item != null) {
            coin = (Coin) item.getContent();
            weight = coin.getWeight();
            //To test chain of responsibility
            //storeCtrl.getCoinStoreItem(weight);
        }
        TransactionController.instance().OnCoinTransaction(weight);
        System.out.println("Coin inserted is " + coinsLabel + " . idx=" + coinIdx + " weight=" + weight);
    }

    public void onSelectDrinkEvent(final StoreItem item, final String drinkLabel, final int drinkId) {
        System.out.println("Drink selected is " + drinkLabel + "and the idx = " + drinkId);
        TransactionController.instance().OnStartTransaction(drinkLabel);
    }

    public void displayCustomerPanel() {
        SimulatorControlPanel scp = mCtrl.getSimulatorControlPanel();
        if (customerPanel == null) {
            customerPanel = new CustomerPanelNew((Frame) scp, this, maintenanceCtrl);
        }
        customerPanel.display();
        //customerPanel.setActive(CustomerPanelNew.DIALOG, true);  // setActive of password, invalid and valid display.
    }
 
    // OBSERVER IMPL BEGIN
	/* (non-Javadoc)
     * @see vmcs.observer.StoreItemObserver#update(vmcs.entity.StoreItem, int)
     */
    @Override
    public void update(StoreItem storeItem, int event) {
        int idx;
        boolean flag;
        String name = storeItem.getContent().getName();
        if( customerPanel != null) {
            if( !TransactionController.instance().getMaintenanceFlag() ){
                if (event == StoreItemChangeManager.EVENT_QUANTITYCOINCHANGE) {
                    int qty = storeItem.getQuantity();
                    flag = ( qty != 0);
                    customerPanel.setActive( CompType.CompCoin, name, flag);            
                } else if (event == StoreItemChangeManager.EVENT_QUANTITYDRINKCHANGE) {
                    int qty = storeItem.getQuantity();
                    flag = ( qty != 0);
                    customerPanel.setActive( CompType.CompDrink, name, flag);
                    customerPanel.setActive( CompType.CompNIS, name, !flag);
                } else if (event == StoreItemChangeManager.EVENT_DRINKVALUECHANGE) { 
                    customerPanel.updateDrinkPrice(name, storeItem);
                } else {
                    throw new ArrayIndexOutOfBoundsException("Invalid type passed: " + event);
                }
            }
            else{
                itemEventMap.put(storeItem, event);
            }
        }
    }
    // OBSERVER IMPL END

    public void refresh(){
        if( !TransactionController.instance().getMaintenanceFlag() ){
            for(Map.Entry<StoreItem, Integer> entry : itemEventMap.entrySet() ){
                StoreItem item = entry.getKey();
                Integer event = entry.getValue();
                update(item, event);
            }
            itemEventMap.clear();
        }
    }
    
    public boolean closeDown() {
        customerPanel.closeDown();
        SimulatorControlPanel smctrl = mCtrl.getSimulatorControlPanel();
        smctrl.setActive(SimulatorControlPanel.ACT_CUSTOMER, true);
        return true;
    }

    public StoreItem[] getStoreItems(char type) {
        return storeCtrl.getStoreItems(type);
    }

    public void onTerminateSelectionEvent() {
        TransactionController.instance().OnResetTransaction();
        onClearSelectedDrink();
    }

    public void onClearSelectedDrink() {
        if (customerPanel != null) {
            customerPanel.setDrinkSelectedLabel("NA");
        }
    }
    
    public void setCoinPanelEnable(boolean f) {
        if (customerPanel != null) {
            customerPanel.setCoinPanelEnable(f);
        }
    }

    public boolean getCoinPanelEnable() {
        if (customerPanel != null) {
            return customerPanel.getCoinPanelEnable();
        }
        return false;
    }

    public void setDrinkPanelEnable(boolean f) {
        if (customerPanel != null) {
            customerPanel.setDrinkPanelEnable(f);
        }
    }

    public void setCoinInvalidFlag(boolean f) {
         if (customerPanel != null) {
            customerPanel.setActive( CompType.CompCoinInvalidLb, null, f);
        }
    }
    
    public void updateTotalCoinInserted(int val) {
         if (customerPanel != null) {
            customerPanel.displayTotalCoinInserted(val);
        }
    }
    
    public void updateDispenseDrink(String drinkbrand){
        if (customerPanel != null) {
            if(drinkbrand != null){
                customerPanel.dispenseDrink(drinkbrand);
                customerPanel.setDrinkSelectedLabel("");
            }
            else{
                customerPanel.dispenseDrink("No Can");
            }
        }
    }
    public void updateReturnChange(int changes){
        if (customerPanel != null) {
            customerPanel.returnChange(changes);
        }
    }

}
